iT邦幫忙

2024 iThome 鐵人賽

DAY 24
0
Software Development

我命由我不由語言 java爬蟲挑戰系列 第 24

java爬蟲挑戰 Day 24 - 條件觸發時通知Discord Bot進行推播

  • 分享至 

  • xImage
  •  

開始之前修正之前的一些bug

SubscribeUser

調整及增加預設值,預設為無訂閱。數字最大為MAX,最小為0。

private Boolean isSubscribe = false;
private Integer lowestPrice = 0;
private Integer highestPrice = Integer.MAX_VALUE;
private Integer lowestFloor = 0;
private Integer highestFloor = Integer.MAX_VALUE;

RentalDetailDTO

之前忘記紀錄的房型及連結,額外補上,爬蟲邏輯就不額外說明了。

String link;
String roomType;

條件觸發時通知Discord Bot進行推播

RentalCrawlerScheduler

這邊偷懶,直接把邏輯寫在排程模組中了,不額外抽出Servcie了。
先對下面的程式碼進行說明。
rentalDetailDTOList是我們之前就已經完成的,從591爬下了的物件資料,allSubscribeUser則是取出所有使用者的訂閱資訊,後面用兩層的迴圈,將所有的使用者資料拿去跟所有爬下來的資料進行比對,如果符合條件則將591的資料推送給訂閱的使用者。

private void fetchRentalData() {
    List<RentalCatalogDTO> list = rentalCrawlerService.fetchLatestRentalCatalog();
    List<RentalDetailDTO> rentalDetailDTOList = list.stream()
            .map(obj -> rentalCrawlerService.fetchRentalDetail(obj)).collect(Collectors.toList());

    // 從資料庫獲取當前用戶的訂閱條件 (假設你有一個方法能獲取用戶條件)
    List<SubscribeUser> allSubscribeUser = subscribeUserRepository.findAll();

    allSubscribeUser.stream().forEach(subscribeUser -> {
        // 根據條件過濾符合的租屋資料
        List<RentalDetailDTO> filteredList = rentalDetailDTOList.stream()
                .filter(detail -> filterBySubscribe(detail, subscribeUser))
                .filter(detail -> filterByPrice(detail, subscribeUser))
                .filter(detail -> filterByFloor(detail, subscribeUser))
                .filter(detail -> filterByRooms(detail, subscribeUser))
                .filter(detail -> filterByItems(detail, subscribeUser))
                .filter(detail -> filterByAddress(detail, subscribeUser))
                .collect(Collectors.toList());

        // 組成 EmbedBuilder
        filteredList.forEach(detail -> {
            EmbedBuilder embedBuilder = new EmbedBuilder();
            embedBuilder.setTitle("租屋資訊");
            embedBuilder.setDescription(detail.getInfo());

            // 將 EmbedBuilder 傳送到 Discord 頻道
            discordBotService.tagUserAndSendMessage(subscribeUser.getChannelId(),subscribeUser.getUserId(), embedBuilder);
            
        });
    });

}

而下面則是迴圈中,判斷是否符合條件的邏輯。另外樓層的資料爬下來的格式不符合我的預期,未來再修正,先掛個TODO。

  • 判斷是否訂閱
// 以下是一些過濾方法的實現
private boolean filterBySubscribe(RentalDetailDTO detail, SubscribeUser subscribeUser) {
    return subscribeUser.getIsSubscribe() == true;
}
  • 判斷是否在價格區間
private boolean filterByPrice(RentalDetailDTO detail, SubscribeUser subscribeUser) {
    int price = Integer.parseInt(detail.getPrice().replaceAll(",", ""));
    return price >= subscribeUser.getLowestPrice() && price <= subscribeUser.getHighestPrice();
}
  • 判斷是否在樓層區間,爬蟲的邏輯錯誤,暫時不過濾
private boolean filterByFloor(RentalDetailDTO detail, SubscribeUser subscribeUser) {
    // String[] floorAndAreaParts = detail.getFloorAndArea().split(" "); //
    // 假設這是樓層的格式
    // int floor = Integer.parseInt(floorAndAreaParts[0]); // 提取樓層
    // return floor >= subscribeUser.getLowestFloor() && floor <=
    // subscribeUser.getHighestFloor();
    return true; // TODO: 樓層邏輯有問題
}
  • 判斷是否符合房型
private boolean filterByRooms(RentalDetailDTO detail, SubscribeUser subscribeUser) {
    // 假設 detail 中有方法能判斷房型是否匹配
    if (subscribeUser.getRooms().size() == 0) {
        return true;
    }

    return subscribeUser.getRooms().contains(detail.getRoomType());
}
  • 判斷是否符合設備要求
private boolean filterByItems(RentalDetailDTO detail, SubscribeUser subscribeUser) {
    // 比對設備是否符合用戶需求
    Set<String> requiredItems = subscribeUser.getItems();
    if (requiredItems.contains("冰箱") && !detail.isHasFridge())
        return false;
    if (requiredItems.contains("洗衣機") && !detail.isHasWasher())
        return false;
    if (requiredItems.contains("電視") && !detail.isHasTv())
        return false;
    if (requiredItems.contains("冷氣") && !detail.isHasCold())
        return false;
    if (requiredItems.contains("熱水器") && !detail.isHasHeater())
        return false;
    if (requiredItems.contains("床") && !detail.isHasBed())
        return false;
    if (requiredItems.contains("衣櫃") && !detail.isHasCloset())
        return false;
    if (requiredItems.contains("第四台") && !detail.isHasFourth())
        return false;
    if (requiredItems.contains("網路") && !detail.isHasWifi())
        return false;
    if (requiredItems.contains("天然瓦斯") && !detail.isHasGas())
        return false;
    if (requiredItems.contains("沙發") && !detail.isHasSofa())
        return false;
    if (requiredItems.contains("桌子") && !detail.isHasTable())
        return false;
    if (requiredItems.contains("陽台") && !detail.isHasBalcony())
        return false;
    if (requiredItems.contains("電梯") && !detail.isHasLift())
        return false;
    if (requiredItems.contains("車位") && !detail.isHasParking())
        return false;
    return true;
}
  • 判斷是否符合地址、地區條件
private boolean filterByAddress(RentalDetailDTO detail, SubscribeUser subscribeUser) {
    // 比對地址是否符合用戶訂閱的地區
    if (subscribeUser.getAddress().size() == 0) {
        return true;
    }
    return subscribeUser.getAddress().stream()
            .anyMatch(address -> detail.getAddress().contains(address));
}

簡單展示

排程觸發後,會將符合的條件推送給我
https://ithelp.ithome.com.tw/upload/images/20240910/20168635hPtqC75jsB.png

git現狀

https://github.com/a951753sxd/rental-crawler
https://ithelp.ithome.com.tw/upload/images/20240910/201686357lv4v9XRyV.png

小結

程式開發已全部完成,明天再看看要複盤一下架構還是做功能展示。


上一篇
java爬蟲挑戰 Day 23 - 完成重置及查看設定的指令
下一篇
Java爬蟲挑戰 Day 25 - 租屋通知機器人(Discord Bot)展示
系列文
我命由我不由語言 java爬蟲挑戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言